package thread;

import java.util.Hashtable;

/**
 * 线程安全：这里就是理解一下：【Java中没有绝对线程安全的类。】
 *  这里以【HashTable】为例，（所有的java提供的线程安全的类，都类似）。
 *  总结：线程安全的类，指的是，调用这些类的某个方法，是线程安全的。但是一组方法的组合，没有保证原子性，所以不是线程安全的。
 *  比如【hashTable#put】方法是线程安全的。但是【hashTable#get、hashTable#put】方法的组合，不加其他的同步手段，就不能保证原子性了，就不是线程安全的了。
 */
public class ThreadSafe {

    /**
     * 线程安全的例子。
     */
    public void safeThread(){
        Hashtable<String,String> hashtable = new Hashtable<>();
        //这段语句一定是线程安全的。
        //对于其他的线程安全的类，要么通过【synchronized】、【CAS】、【Lock】等不同的实现手段，都可以使单个方法的调用，变成线程安全。
        hashtable.put("k1","v1");
    }

    /**
     * 一个线程安全的类：出现了线程不安全的情况。
     *      这段代码的组合，【不是线程安全的。】
     *      在多线程的情况下，很可能向【hashTable】中添加两条【k1】。
     */
    public void unsafeThread(){
        Hashtable<String,String> hashtable = new Hashtable<>();
        //1：线程A，先判断是否存在【k1】。3：线程B，再判断是否存在【k1】，由于第二步卡住了，所以线程B也会进入这个方法中。
        if(hashtable.contains("k1")){
            //2：此时，线程A，结束了CPU的调用。4：线程A、B先后向【hashTable】中添加了【k1】。导致了线程不安全。
            hashtable.put("k1","v1");
        }
    }

    /**
     * 通过外部的手段，使一些组合变成线程安全的。
     */
    public void safeThreadCom(){
        Hashtable<String,String> hashtable = new Hashtable<>();
        synchronized (ThreadSafe.class){
            if(hashtable.contains("k1")){
                hashtable.put("k1","v1");
            }
        }
    }

}
